﻿using System;
using System.IO;
using PPI.Client.Logic.Distribution;
using PPI.Entities.Distribution;
using PPI.Entities.Enumerator;
using PPI.General;

namespace PPI.Client.Logic.Upload
{
    public class LDistributionImageRecovery
    {
        #region - Events -

        public event EventHandler DataBaseChanged;
        public event EventHandler ImageChanged;
        public event EventHandler ProcessFinished;

        public delegate void UploadErrorEventHandler(UploadingExceptionEventArg errorEventArgs);
        public event UploadErrorEventHandler UploadError;

        #endregion

        #region - Private attributes -

        private string actualDataBaseName;
        private int actualNumberOfDataBase;

        private string actualImageFileName;
        private int actualNumberOfImage;
        private int totalImagesInDataBase;

        #endregion

        #region - Properties -

        public DatabaseTypes DataBaseType { get; set; }
        public FileInfo[] FilesToCheck { get; set; }

        public string ActualDataBaseName
        {
            get
            {
                return actualDataBaseName;
            }
        }

        public string ActualImageFileName
        {
            get
            {
                return actualImageFileName;
            }
        }

        public int ActualNumberOfDataBase
        {
            get
            {
                return actualNumberOfDataBase;
            }
        }

        public int ActualNumberOfImage
        {
            get
            {
                return actualNumberOfImage;
            }
        }

        /// <summary>
        /// Returns the total number of databases uploaded
        /// </summary>
        public int TotalOfDatabases
        {
            get
            {
                return GetSentPaths().Length;
            }
        }

        /// <summary>
        /// Returns the total number of databases uploaded
        /// </summary>
        public int TotalOfImagesInDataBase
        {
            get
            {
                return totalImagesInDataBase;
            }
        }

        #endregion

        #region - Public methods -

        ///// <summary>
        ///// Starts the recovery process
        ///// </summary>
        //public void Start()
        //{
        //    DirectoryInfo[] sentPaths = GetSentPaths();
        //    metersWithoutImages = LMeter.SelectAllWithoutImage();
        //    actualNumberOfDataBase = 0;

        //    foreach (DirectoryInfo path in sentPaths)
        //    {
        //        string fileName = GetDataBaseFileName(path);
        //        FileInfo fInfo = new FileInfo(fileName);
        //        actualDataBaseName = fInfo.Name;
        //        actualNumberOfDataBase++;
        //        actualNumberOfMeter = 0;

        //        List<EMeter> meters = LMeter.GetMeters(fileName);
        //        totalImagesInDataBase = meters.Count;

        //        if (DataBaseChanged != null)
        //            DataBaseChanged(this, EventArgs.Empty);

        //        Update(meters, fileName);
        //    }

        //    if (ProcessFinished != null)
        //        ProcessFinished(this, EventArgs.Empty);
        //}

        /// <summary>
        /// Starts the recovery process
        /// </summary>
        public void Start()
        {
            actualNumberOfDataBase = 0;

            foreach (FileInfo file in FilesToCheck) 
            {
                actualDataBaseName = file.Name;
                actualNumberOfDataBase++;

                if (DataBaseChanged != null)
                    DataBaseChanged(this, EventArgs.Empty);
                
                Update(file.FullName);
            }

            if (ProcessFinished != null)
                ProcessFinished(this, EventArgs.Empty);
        }

        #endregion

        #region - Private methods -

        /// <summary>
        /// Updates the poles
        /// </summary>
        /// <param name="connectionString"></param>
        private void Update(string connectionString)
        {
            var poles = LPole.GetDistributionPoles(connectionString);
            string _imageDirectory = DirHelper.GetImagesDirectory(connectionString);

            actualNumberOfImage = 0;
            totalImagesInDataBase = 0;
            foreach (var actualPole in poles) {
                totalImagesInDataBase += actualPole.Images.Count;

                foreach (var meter in actualPole.Meters)
                    if (!string.IsNullOrEmpty(meter.Image.FileName))
                        totalImagesInDataBase++;
            }

            if (DataBaseChanged != null)
                DataBaseChanged(this, EventArgs.Empty);

            try
            {
                foreach (EDistributionPole pole in poles)
                {
                    foreach (EDistributionPoleImage poleImage in pole.Images)
                    {

                        actualImageFileName = poleImage.FileName;
                        actualNumberOfImage++;
                        if (ImageChanged != null)
                            ImageChanged(this, EventArgs.Empty);

                        var file = new FileInfo(_imageDirectory + Path.DirectorySeparatorChar + poleImage.FileName);

                        if (file.Exists)
                        {
                            string _FileName = pole.ServerID + "_" + poleImage.ServerID + ".jpg";
                            string _FolderName = DirHelper.GetImageDirectory(pole.ServerID, poleImage.ServerID);
                            string mode = ConfigReader.GetInstance().GetConnectionString();
                            string url = Constants.K_SERVERBASEURL + mode + "/IMAGES/" +
                                         DatabaseTypes.DistributionInspection + "/" + _FolderName + "/" + _FileName;

                            //Check if images is on server
                            var uploaderHelper = new WebUploaderHelper(url);
                            int valor = uploaderHelper.FileSizeOnServer();

                            if (valor == 0)
                            {
                                uploaderHelper = new WebUploaderHelper(Constants.K_WEBSITEUPLOADER);
                                uploaderHelper.Upload(_FolderName, _FileName, file,
                                                      DatabaseTypes.DistributionInspection.ToString());
                            }
                        }
                    }

                    foreach (var distributionMeter in pole.Meters)
                    {
                        actualImageFileName = distributionMeter.Image.FileName;
                        actualNumberOfImage++;
                        if (ImageChanged != null)
                            ImageChanged(this, EventArgs.Empty);

                        var file = new FileInfo(_imageDirectory + Path.DirectorySeparatorChar + distributionMeter.Image.FileName);
                        if (file.Exists)
                        {
                            string _FileName = pole.ServerID + "_" + distributionMeter.ServerId + ".jpg";
                            string _FolderName = DirHelper.GetImageDirectory(pole.ServerID, distributionMeter.ServerId);
                            string mode = ConfigReader.GetInstance().GetConnectionString();
                            string url = Constants.K_SERVERBASEURL + mode + "/IMAGES/" + DatabaseTypes.DistributionInspection + "MeterImages/" + _FolderName + "/" + _FileName;

                            //Check if images is on server
                            var uploaderHelper = new WebUploaderHelper(url);
                            int valor = uploaderHelper.FileSizeOnServer();

                            if (valor == 0)
                            {
                                uploaderHelper = new WebUploaderHelper(Constants.K_WEBSITEUPLOADER);
                                uploaderHelper.Upload(_FolderName, _FileName, file, DatabaseTypes.DistributionInspection + "MeterImages");
                            }
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                string message = "An error has occured while processing poles in file " + connectionString;
                var exceptionEvent = new UploadingExceptionEventArg(message, exc);

                if (UploadError != null)
                    UploadError(exceptionEvent);
            }
        }

        /*
        /// <summary>
        /// Updates the meters
        /// </summary>
        /// <param name="meters"></param>
        /// <param name="connectionString"></param>
        private void Update(IEnumerable<EMeter> meters, string connectionString)
        {
            foreach (EMeter meter in meters)
            {
                actualImageFileName = meter.Image.FileName;
                actualNumberOfPole++;

                if (PoleChanged != null)
                    PoleChanged(this, EventArgs.Empty);

                int index = metersWithoutImages.FindIndex(delegate(EMeter item) { return item.ServerId == meter.ServerId; });

                if (index >= 0)
                    UploadImage(meter, connectionString);
            }
        }
        */

        /// <summary>
        /// Uploads the image to the server
        /// </summary>
        /// <param name="meter"></param>
        /// <param name="connectionString"></param>
        private void UploadImage(EMeter meter, string connectionString)
        {
            //
            bool imageUploaded = false;
            try
            {
                string _imageDirectory = DirHelper.GetImagesDirectory(connectionString);
                var file = new FileInfo(_imageDirectory + Path.DirectorySeparatorChar + meter.Image.FileName);
                string _FileName = meter.PoleServerId + "_" + meter.ServerId + ".jpg";
                string _FolderName = DirHelper.GetImageDirectory(meter.PoleServerId, meter.ServerId);
                imageUploaded = false;

                int count = 0;
                var _UploaderHelper = new WebUploaderHelper(Constants.K_WEBSITEUPLOADER);
                if (file.Exists)
                {
                    count++;

                    _UploaderHelper.Upload(_FolderName, _FileName, file, Enum.GetName(typeof(DatabaseTypes),DataBaseType) + "MeterImages");

                    imageUploaded = true;

                    string originalFileName = meter.Image.FileName;
                    meter.Image.FileName = _FileName;
                    LPole.SaveMeterImage(meter.Image, meter.ServerId);
                    meter.Image.FileName = originalFileName;
                }
            }
            finally
            {
                LImage.UpdateMeterImageUploadedData(meter.Id, imageUploaded, connectionString);
            }
        }

        /// <summary>
        /// Gets all the subpaths in the Sent Application Path
        /// </summary>
        /// <returns></returns>
        private static DirectoryInfo[] GetSentPaths()
        {
            DirectoryInfo sentAppDirectory = new DirectoryInfo(Constants.K_SENTDISTRIBUTIONINSPECTIONFOLDERS);
            DirectoryInfo [] sentDirectories = sentAppDirectory.GetDirectories();

            return sentDirectories;
        }

        /// <summary>
        /// Gets the database file name that is in the path
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private static string GetDataBaseFileName(DirectoryInfo path)
        {
            FileInfo [] files = path.GetFiles("*.sdf");

            if (files.Length > 0)
                return files[0].FullName;

            return string.Empty;
        }

        #endregion
    }

    public class UploadingExceptionEventArg : EventArgs
    {
        public string Message {get;set;}
        public Exception Exception { get; set; }

        public UploadingExceptionEventArg(string message, Exception exception)
        {
            Message = message;
            Exception = exception;
        }
    } 
}
